package pruebas.naves;


import static org.junit.Assert.*;
import org.junit.*;
import static modelo.SetUps.ENERGIA_ALGO42;
import static modelo.SetUps.VELOCIDAD_ALGO42;
import static modelo.SetUps.ENERGIA_CAZA;
import static modelo.SetUps.RADIO_RASTREO;
import static modelo.SetUps.TOLERANCIA;
import modelo.armas.*;
import modelo.desplazadores.DesplazadorLineaRecta;
import modelo.naves.Avioneta;
import modelo.naves.EnergiaAgotadaException;
import modelo.naves.NaveAlgo42;
import modelo.util.Vector;

public class TestAlgo42 {
	private Vector p1 = new Vector(0,10);//una posicion donde crear la nave
	private Vector p2 = new Vector (1,0);
	private NaveAlgo42 algo42;
	
	@Before
	public void setUp() throws Exception {
		algo42 = new NaveAlgo42(p1,p2);
	}
	
	@Test
	public void testInicializacion() {
		assertEquals("inicializacion incorrecta de posicion en algo42",
				p1, algo42.getPosicion());
		assertEquals("inicializacion incorrecta de posicion en algo42",
				ENERGIA_ALGO42, algo42.getEnergia());
	}
	
	@Test
	public void testMovimiento() {
		DesplazadorLineaRecta desplazador = new DesplazadorLineaRecta(p1, p2,
				VELOCIDAD_ALGO42);
		for (int i = 0; i < 5; i++) {
			algo42.setDirProxMov(p2);
			
			algo42.mover();
			desplazador.mover();
			assertEquals(
					"movimiento incorrecto en algo42, al mover mas de una vez",
					desplazador.getPosicion(), algo42.getPosicion());
		}
	}
	
	@Test (expected = EnergiaAgotadaException.class)
	public void testDanio(){
		//aplico a la algo42 un danio mayor a su energia
		algo42.recibirDisparo(ENERGIA_ALGO42 + 5);
		assertEquals("energia en algo42 no se descuenta adecuadamente",
				(-5), algo42.getEnergia());
		assertFalse("algo42 no debe permitir seguir actuando con su energia agotada",
				algo42.seguirActuando());
		//al intentar moverse debe lanzar una excepcion
		algo42.mover();
	}
	
	@Test
	public void testDisparar(){
		algo42.setDisparo();
		//debe devolver una bala enemiga de laser
		BalasAlgo42 bala = (BalasAlgo42)algo42.disparar();
		// para chequear esto la hago chocar con una nave enemiga
		Avioneta nave = new Avioneta (p1, p2);
		bala.chocarCon(nave);
		assertFalse ("disparo incorrecto",
				bala.seguirActuando());
	}
	
	/*
	 * test varios de colisiones
	 */
	
	@Test
	public void testColisionConNavesAutonomas(){
		Avioneta nave = new Avioneta (p1,p2);
		//deben chocar espacialmente
		assertTrue ("deberian poder chocarse las dos naves",
				algo42.chocaCon(nave));
		algo42.chocarCon(nave);
		//ambas naves deben morir
		algo42.chocarCon(nave);
		assertFalse("el algo 42 no debe seguir actuando",
				algo42.seguirActuando());
		assertFalse ("la nave no debe seguir actuando",
				nave.seguirActuando());
	}
	
	@Test
	public void testColisionConBalaEnemiga (){
		//disparar una bala de laser enemigo
		Laser arma = new Laser (new BandoEnemigo());
		Balas bala = arma.disparar(p1, p2);
		//deben poder chocarse
		assertTrue ("la bala y algo42 deben podeer chocarse",
				algo42.chocaCon(bala));
		algo42.chocarCon(bala);
		//deben afectarse
		assertTrue ("algo 42 debe verse afectado",
				algo42.getEnergia() < ENERGIA_ALGO42);
		assertFalse ("la bala no debe seguir actuando",
				bala.seguirActuando());
	}
	
	@Test
	public void testColisionConBalaAlgo42 (){
		//disparar una bala de laser de algo42
		Laser arma = new Laser (new BandoAlgo42());
		Balas bala = arma.disparar(p1, p2);
		//deben poder chocarse
		assertTrue ("la bala y la nave deben podeer chocarse",
				algo42.chocaCon(bala));
		algo42.chocarCon(bala);
		//no deben afectarse
		assertEquals ("la nave no debe verse afectada",
				ENERGIA_ALGO42, algo42.getEnergia());
		assertTrue ("la bala debe seguir actuando",
				bala.seguirActuando());
	}
	
	@Test
	public void testColisionConRadarEnemigo(){
		RadarEnemigo radar = new RadarEnemigo (p1, p2);
		//deben poder chocarse
		assertTrue ("el radar y el algo 42 deben podeer chocarse",
				algo42.chocaCon(radar));
		algo42.chocarCon(radar);
		//deben afectarse
		assertEquals ("el algo42 no debe verse afectado",
				ENERGIA_ALGO42, algo42.getEnergia());
		assertFalse ("el radar no debe seguir actuando",
				radar.seguirActuando());
	}
	
	@Test
	public void testColisionConRadarAlgo42(){
		RadarAlgo42 radar = new RadarAlgo42 (p1, p2);
		//deben poder chocarse
		assertTrue ("el radar y el algo42 deben poder chocarse",
				algo42.chocaCon(radar));
		algo42.chocarCon(radar);
		//no deben afectarse
		assertEquals ("el algo42 no debe verse afectado",
				ENERGIA_ALGO42, algo42.getEnergia());
		assertTrue ("el radar debe seguir actuando",
				radar.seguirActuando());
	}
	
	@Test
	public void testColisionConPickUpEnergiaCaza(){
		PickUpEnergiaCaza pickUp = new PickUpEnergiaCaza (p1, p2);
		//deben poder chocarse
		assertTrue ("el pickUp y el algo42 deben podeer chocarse",
				algo42.chocaCon(pickUp));
		algo42.chocarCon(pickUp);
		//deben afectarse
		assertEquals ("el algo 42 debe aumentar su energia",
				ENERGIA_ALGO42 + ENERGIA_CAZA , algo42.getEnergia());
		assertFalse ("el pickUp no debe seguir actuando",
				pickUp.seguirActuando());
	}
	
	@Test
	public void testColisionConPickUpArmaBombardero(){
		PickUpArmaBombardero pickUp = new PickUpArmaBombardero (p1, p2);
		//deben poder chocarse
		assertTrue ("el pickUp y el algo42 deben podeer chocarse",
				algo42.chocaCon(pickUp));
		algo42.chocarCon(pickUp);
		//deben afectarse
		algo42.setDisparo();
		Radar radar = (Radar)algo42.disparar();
		assertEquals ("el algo 42 debe cambiar su arma",
				 radar.getRadio(), RADIO_RASTREO, TOLERANCIA);
		assertFalse ("el pickUp no debe seguir actuando",
				pickUp.seguirActuando());
	}
}
